---@module mqttOutMsg
--- 模块功能：MQTT客户端数据发送处理
-- @author openLuat
-- @module mqtt.mqttOutMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
require "net"
require "sim"
require "mylbsLoc"
require "deviceConfig"
require "config"
require "tool"
module(..., package.seeall)
local LOG_PREFIX = "MQTTOUTMSG"

local wantSendAllOne = false -- 标记是否需要一次全量发送
-- 数据发送的消息队列
local msgQuene = {}

-- 华为云物模型服务的缓存 是为了避免重复发一样的内容过去，保存上次的发送值，与serviceConfig 保持一致
local serviceConfCache = {}

function insertMsg(topic, payload, qos, user)
    table.insert(msgQuene, {t = topic, p = payload, q = qos, user = user})
    sys.publish("APP_SOCKET_SEND_DATA")
end

-- 将payload变为json再发送
function insertMsg2Json(topic, payload, qos, user)
    local jsonstr = json.encode(payload)
    log.info("insertMsg2Json", ",topic =" .. topic .. "-payload=" .. jsonstr)
    insertMsg(topic, jsonstr, qos, user)
end

---- 推送系统信息(只一次)
-- local function pubSysInfoOne()
--    local local_lat = "0"
--    local local_lng = "0"
--    -- 20200410 发送经纬度
--    mylbsLoc.request(function(result,lat,lng,addr)
--        --re["lbsLocRes"] = result
--        log.info("power on info send mqtt")
--        tool.print_dump(result)
--        tool.print_dump(lat)
--        tool.print_dump(lng)
--        if result == 0 then
--            local_lat = lat
--            local_lng = lng
--        end
--        sys.publish("LBSLOCREQUESt")
--    end ,nil,20000)
--    sys.waitUntil("LBSLOCREQUESt", 21000)
--    re = {
--        services = {
--            {
--                service_id = "base",
--                properties = {
--                    project = _G.PROJECT,
--                    csq = net.getRssi(),
--                    imei = misc.getImei(),
--                    version = _G.VERSION,
--                    osversion = rtos.get_version(),
--                    lat = local_lat,
--                    lng = local_lng
--                }
--            }
--        },
--    }
--    tool.print_dump(re)
--    insertMsg2Json(_G.MQTT_TOPIC_PROREPORT, re, 0, { cb = pubSysInfoOneCb })
-- end

--- 初始化“MQTT客户端数据发送”
-- @return 无
-- @usage mqttOutMsg.init()
function init()
    -- pubSysInfoOne()
    startServicePubTask()
end

--- 去初始化“MQTT客户端数据发送”
-- @return 无
-- @usage mqttOutMsg.unInit()
function unInit()
    -- 20200426 去掉循环发送configdiff的线程
    sys.publish("MQTT_CUSTOM_TASK_KILL")
    while #msgQuene > 0 do
        local outMsg = table.remove(msgQuene, 1)
        if outMsg.user and outMsg.user.cb then
            outMsg.user.cb(false, outMsg.user.para)
        end
    end
end

--- MQTT客户端是否有数据等待发送
-- @return 有数据等待发送返回true，否则返回false
-- @usage mqttOutMsg.waitForSend()
function waitForSend() return #msgQuene > 0 end

--- MQTT客户端数据发送处理
-- @param mqttClient，MQTT客户端对象
-- @return 处理成功返回true，处理出错返回false
-- @usage mqttOutMsg.proc(mqttClient)
function proc(mqttClient)
    while #msgQuene > 0 do
        local outMsg = table.remove(msgQuene, 1)
        log.info("mqttClient:publish", outMsg.t .. outMsg.p)
        local result = mqttClient:publish(outMsg.t, outMsg.p, outMsg.q)
        if outMsg.user and outMsg.user.cb then
            outMsg.user.cb(result, outMsg.user.para)
        end
        if not result then return end
    end
    return true
end

-- 发送sensor service 与华为云里面的配置保持一致
-- isall 是否全量发生
function sendHwService(isall)
    local newservices = tool.deepCopy(serviceConfig.getData())
    local body = {}

    if isall then
        body = {services = {}}
        for k, v in pairs(newservices) do
            local s = {service_id = k, properties = v}
            table.insert(body.services, s)
        end

        insertMsg2Json(_G.MQTT_TOPIC_PROREPORT, body, 0, {cb = pubSysInfoOneCb})
    else
        -- 重量变化即发送数据
        if math.abs(newservices.sensor.weightval -
                        serviceConfCache.sensor.weightval) > 1 then
            body = {services = {}}
            for k, v in pairs(newservices) do
                local s = {service_id = k, properties = v}
                table.insert(body.services, s)
            end

            insertMsg2Json(_G.MQTT_TOPIC_PROREPORT, body, 0,
                           {cb = pubSysInfoOneCb})
        end
    end

    -- 缓存
    serviceConfCache = tool.deepCopy(newservices)
end

--- MQTT 隔1分钟左右自动上报发送状态信息
function startServicePubTask()
    sys.taskInit(function()
        log.info("mqttOutMsg", "--hw service send start")
        -- 第一次全量发送
        sys.wait(5000)
        sendHwService(true)
        -- 隔5分钟必定进行一次全量上报
        local count = 0
        sys.wait(5000)
        while true do
            if count == 4 then
                log.info("mqttOutMsg", "--5min all push")
                wantSendAllOne = true
            end
            if wantSendAllOne == true then
                sendHwService(true)
                -- 需要一次全量发送
                wantSendAllOne = false
            else
                sendHwService(false)
            end

            local result1, data1 = sys.waitUntil("MQTT_CUSTOM_TASK_KILL",
                                                 60 * 1000)
            if result1 == true then
                break -- mqtt断开了退出线程
            end
            count = count + 1
            if count > 4 then count = 0 end
        end
        log.info("mqttOutMsg", "--diff send return")
    end)
end

-- 华为云通过命令要求需要进行一次全量发送
function wantSendServiceAll() wantSendAllOne = true end

